#pragma once

#include "../communal/Communication.hpp"
#include "../communal/Message.hpp"
#include <thread>

namespace xu
{
    namespace server
    {
        // 枚举json类型
        enum class VType
        {
            BOOL = 0,
            INTEGRAL,
            NUMERIC,
            STRING,
            ARRAY,
            OBJECT
        };

        // 描述类 --描述服务的参数、返回值等
        class ServiceDescribe
        {
        public:
            using Ptr = std::shared_ptr<ServiceDescribe>;
            using vt = std::pair<std::string, VType>;
            using ServiceCallback = std::function<void(const Json::Value &, Json::Value &)>;

            // 构造函数
            ServiceDescribe(std::string &&method, std::vector<vt> &&parameter, VType restype, ServiceCallback &&callback)
                : _method(std::move(method)),
                  _parameter(std::move(parameter)),
                  _restype(restype),
                  _callback(std::move(callback))
            {
            }
            // 检测参数是否符合标准
            bool ParameterCheck(const Json::Value &req)
            {
                for (auto &e : _parameter)
                {
                    if (req.isMember(e.first) == false)
                    {
                        LOG(LogLevel::ERROR) << "参数不存在";
                        return false;
                    }

                    if (Check(req[e.first], e.second) == false)
                    {
                        LOG(LogLevel::ERROR) << "参数类型错误";
                        return false;
                    }
                }

                return true;
            }

            // 返回method
            const std::string &Method()
            {
                return _method;
            }

            // 调用函数
            bool call(const Json::Value &req, Json::Value &rsp)
            {
                _callback(req, rsp);

                if (ResCheck(rsp) == false)
                {
                    return false;
                }

                return true;
            }

        private:
            // 检测返回值类型是否符合
            bool ResCheck(const Json::Value &rsp)
            {
                if (Check(rsp, _restype) == false)
                {
                    LOG(LogLevel::ERROR) << "参数类型错误";
                    return false;
                }

                return true;
            }
            bool Check(const Json::Value &val, const VType vtype)
            {
                switch (vtype)
                {
                case VType::BOOL:
                    return val.isBool();
                case VType::INTEGRAL:
                    return val.isIntegral();
                case VType::NUMERIC:
                    return val.isNumeric();
                case VType::ARRAY:
                    return val.isArray();
                case VType::STRING:
                    return val.isString();
                case VType::OBJECT:
                    return val.isObject();
                default:
                    break;
                }

                return false;
            }

        private:
            std::string _method;        // 服务名称
            std::vector<vt> _parameter; // 参数描述
            VType _restype;             // 返回值类型
            ServiceCallback _callback;  // 回调函数
        };

        // 建造者类
        class SDescribeFactory
        {
        public:
            using Ptr = std::shared_ptr<SDescribeFactory>;
            void SetMethod(const std::string &method)
            {
                _method = method;
            }

            void SetParameter(const std::string &pname, const VType &vtype)
            {
                _parameter.push_back(std::make_pair(pname, vtype));
            }

            void SetRestype(const VType &restype)
            {
                _restype = restype;
            }

            void SetCallback(const ServiceDescribe::ServiceCallback callback)
            {
                _callback = callback;
            }

            ServiceDescribe::Ptr Build()
            {
                return std::make_shared<ServiceDescribe>(std::move(_method), std::move(_parameter), _restype, std::move(_callback));
            }

        private:
            std::string _method;                         // 服务名称
            std::vector<ServiceDescribe::vt> _parameter; // 参数描述
            VType _restype;                              // 返回值类型
            ServiceDescribe::ServiceCallback _callback;  // 回调函数
        };

        // 管理类
        class ServiceManager
        {
        public:
            using Ptr = std::shared_ptr<ServiceManager>;

            // 插入
            void Insert(const ServiceDescribe::Ptr &serve)
            {
                std::unique_lock<std::mutex> _look(_mutex);
                _manage_serve.insert(std::make_pair(serve->Method(), serve));
            }

            //获取
            ServiceDescribe::Ptr Select(const std::string &method)
            {
                std::unique_lock<std::mutex> _look(_mutex);
                auto it = _manage_serve.find(method);
                if (it == _manage_serve.end())
                {
                    return ServiceDescribe::Ptr();
                }

                return it->second;
            }

            // 删除
            void Remove(const std::string &method)
            {

                std::unique_lock<std::mutex> _look(_mutex);
                _manage_serve.erase(method);
            }

            //提供过的主题名称
            std::vector<std::string> GetMethod()
            {
                std::unique_lock<std::mutex> _look(_mutex);
                std::vector<std::string> ret;
                for (auto &e : _manage_serve)
                {
                    ret.push_back(e.first);
                }

                return ret;
            }

        private:
            std::mutex _mutex;
            std::unordered_map<std::string, ServiceDescribe::Ptr> _manage_serve;
        };

        class RpcRouter
        {
        public:
            const int boundary = 2;
            using Ptr = std::shared_ptr<RpcRouter>;

            RpcRouter() : _sm(std::make_shared<ServiceManager>()),
                          _overload(false),
                          _reqnumber(0),
                          _enableRegistry(false)
            {
            }
            // 注册
            void RegisteredServe(const ServiceDescribe::Ptr &serve)
            {
                return _sm->Insert(serve);
            }

            // 调用v
            void RpcRequest(const BaseConnection::Ptr &conn, const RpcRequest::Ptr &req)
            {

                // 单进程模式
                //  1.是否能提过服务
                //  auto serve = _sm->Select(req->Method());
                //  if (serve.get() == nullptr)
                //  {
                //      LOG(LogLevel::ERROR) << "不存在该服务";
                //      return response(conn, req, Json::Value(), RCode::RCODE_NOT_FOUND_SERVICE);
                //  }
                //  LOG(LogLevel::DEBUG) << "存在该服务";

                // // 2.参数是否符合
                // if (serve->ParameterCheck(req->Params()) == false)
                // {
                //     return response(conn, req, Json::Value(), RCode::RCODE_INVALID_PARAMS);
                // }
                // LOG(LogLevel::DEBUG) << "参数符合";

                // // 3.进行调用
                // if (_enableRegistry)
                // {
                //     std::unique_lock<std::mutex> _lock(_mutex);
                //     ++_reqnumber;
                //     if (_overload == false && _reqnumber >= boundary)
                //     {
                //         _overload = true;
                //         request(true);
                //     }
                //     LOG(LogLevel::DEBUG) << "_reqnumber: " << _reqnumber;
                // }

                // LOG(LogLevel::DEBUG) << "进行调用";
                // // if(serve->call(req->Params(),rse) == false)
                // // {
                // //     return response(conn,req,Json::Value(),RCode::RCODE_INTERNAL_ERROR);
                // // }
                // // LOG(LogLevel::DEBUG)<<"进行调用";

                // 4.返回结果
                // response(conn,req,rse,RCode::RCODE_OK);

                // if(_enableRegistry)
                // {
                //     std::unique_lock<std::mutex> _lock(_mutex);
                //     --_reqnumber;
                //     if(_overload == true && _reqnumber < boundary)
                //     {
                //         _overload = false;
                //         request(false);
                //     }
                //     LOG(LogLevel::DEBUG)<<"_reqnumber: "<< _reqnumber;
                // }

                // 多线程方式  --可使用线程池
                std::thread th([this](const BaseConnection::Ptr &conn, const RpcRequest::Ptr &req)
                               {
                               // 1.是否能提过服务
                               auto serve = _sm->Select(req->Method());
                               if (serve.get() == nullptr)
                               {
                                   LOG(LogLevel::ERROR) << "不存在该服务";
                                   return response(conn, req, Json::Value(), RCode::RCODE_NOT_FOUND_SERVICE);
                               }
                               LOG(LogLevel::DEBUG) << "存在该服务";

                               // 2.参数是否符合
                               if (serve->ParameterCheck(req->Params()) == false)
                               {
                                   return response(conn, req, Json::Value(), RCode::RCODE_INVALID_PARAMS);
                               }
                               LOG(LogLevel::DEBUG) << "参数符合";

                               // 3.进行调用
                               if (_enableRegistry)
                               {
                                   std::unique_lock<std::mutex> _lock(_mutex);
                                   ++_reqnumber;
                                   if (_overload == false && _reqnumber >= boundary)
                                   {
                                       _overload = true;
                                       request(true);
                                   }
                                   LOG(LogLevel::DEBUG) << "_reqnumber: " << _reqnumber;
                               }

                               LOG(LogLevel::DEBUG) << "进行调用";
                               Json::Value rse;
                               serve->call(req->Params(), rse);
                               if (_enableRegistry)
                               {
                                   std::unique_lock<std::mutex> _lock(_mutex);
                                   --_reqnumber;
                                   if (_overload == true && _reqnumber < boundary)
                                   {
                                       _overload = false;
                                       request(false);
                                   }
                                   LOG(LogLevel::DEBUG) << "_reqnumber: " << _reqnumber;
                               }
                               response(conn, req, rse, RCode::RCODE_OK);
                               LOG(LogLevel::DEBUG) << "返回结果成功"; }, conn, req);
                th.detach();
            }

            void SetAddr(const Address &addr)
            {
                _addr = addr;
            }

            void SetEnableRegistry(bool enableRegistry)
            {
                _enableRegistry = enableRegistry;
            }

            void SetConn(const BaseConnection::Ptr &conn)
            {
                _conn = conn;
            }

        private:
            void request(bool overload)
            {
                std::vector<std::string> ret = _sm->GetMethod();
                LOG(LogLevel::DEBUG) << "开始发送负载情况";
                for (auto &e : ret)
                {
                    auto req = MessageFactory::create<ServiceRequest>();
                    req->SetId(UUID::uuid());
                    req->SetHost(_addr);
                    req->SetOptype(ServiceOptype::SERVICE_OVERLOAD);
                    req->SetOverload(overload);
                    req->SetMethod(e);
                    req->SetMType(MType::REQ_SERVICE);

                    _conn->Send(req);
                }
            }
            // 组织返回
            void response(const BaseConnection::Ptr &conn,
                          const RpcRequest::Ptr &req,
                          const Json::Value &res, RCode rcode)
            {
                auto rsp = MessageFactory::create<RpcResponse>();
                rsp->SetId(req->Id());
                rsp->SetMType(MType::RSP_RPC);
                rsp->SetRcode(rcode);
                rsp->SetResult(res);

                conn->Send(rsp);
            }

        private:
            std::mutex _mutex;
            bool _overload;
            int _reqnumber;
            Address _addr;
            bool _enableRegistry;
            BaseConnection::Ptr _conn;
            ServiceManager::Ptr _sm;
        };
    }
};
